<template>
    <div class="container">
        <el-form :inline="true" :model="formModel" class="form" :style="style" :label-width="formLabelWidth" :size="formSize" status-icon>
            <!-- 表单项 -->
            <div class="form-item" ref="scrollFormRef" v-has-permission="searchPermission">
                <el-form-item v-for="(item, index) in formItem" :key="index" :label="item.label">
                    <component :is="renderFormItem(item, index)" />
                </el-form-item>
                <slot name="items"></slot>
            </div>
            <!-- 表单按钮 -->
            <div class="form-btn">
                <el-form-item class="form-btn-item" :key="formBtnKey">
                    <slot name="frontBtn"></slot>
                    <component :is="renderButtons()" />
                    <slot name="afterBtn"></slot>
                    <component :is="renderExpandButton()" />
                </el-form-item>
            </div>
        </el-form>
    </div>

    <!-- 全屏搜索弹窗 -->
    <el-dialog v-model="isFullScreen" fullscreen>
        <el-form :inline="true" :model="formModel" class="form-dialog" :style="style" :label-width="formLabelWidth" :size="formSize" status-icon>
            <!-- 表单项 -->
            <el-form-item v-for="(item, index) in formItem" :key="index" :label="item.label" v-has-permission="searchPermission">
                <component :is="renderFormItem(item, index)" />
            </el-form-item>
            <slot name="items"></slot>
            <el-form-item :key="formBtnKey">
                <slot name="frontBtn"></slot>
                <component :is="renderButtons()" />
                <slot name="afterBtn"></slot>
                <component :is="renderExpandButton()" />
            </el-form-item>
        </el-form>
    </el-dialog>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted, h, Fragment, type VNode } from "vue";
import { debounce } from "lodash-es";
import { Search, Close, Plus } from "@element-plus/icons-vue";
import { ElButton, ElInput, ElInputNumber, ElSelect, ElOption, ElTreeSelect, ElDatePicker, ElTimePicker, ElTooltip, type ComponentSize } from "element-plus";
import { hasPermission, extend, shrink } from "@/utils/common";

//接收父类传过来的参数
interface Props {
    formModel: Record<string, any>;
    style?: Record<string, any>;
    formLabelWidth?: string;
    formSize?: ComponentSize;
    formItem?: Record<string, any>;
    showSearch?: boolean;
    showClear?: boolean;
    showAdd?: boolean;
    showExpand?: boolean;
    searchPermission?: string;
    addPermission?: string;
}
const props = withDefaults(defineProps<Props>(), {
    formModel: () => ({}),
    style: () => ({}),
    formLabelWidth: "80px",
    formSize: "default",
    formItem: () => ({}),
    showSearch: true,
    showClear: true,
    showAdd: true,
    showExpand: true,
    searchPermission: "PAGE",
    addPermission: "INSERT",
});

//按钮大小
const size = ref<ComponentSize>("default");

//是否是全屏
const isFullScreen = ref(false);

//渲染表单项
const renderFormItem = (item: any, key: string) => {
    switch (item.type) {
        case "input":
            return h(ElInput, {
                modelValue: props.formModel[key],
                "onUpdate:modelValue": (value: any) => {
                    props.formModel[key] = value;
                },
                placeholder: item.placeholder ? item.placeholder : `请输入${item.label}`,
                maxlength: item.maxlength,
                showWordLimit: item.showWordLimit,
                clearable: item?.clearable ? item.clearable : true,
                prefixIcon: item.prefixIcon,
                suffixIcon: item.suffixIcon,
                style: item.style,
                size: item.size,
            });
        case "number":
            return h(ElInputNumber, {
                modelValue: props.formModel[key],
                "onUpdate:modelValue": (value: any) => {
                    props.formModel[key] = value;
                },
                placeholder: item.placeholder ? item.placeholder : `请输入${item.label}`,
                min: item.min,
                max: item.max,
                step: item.step,
                clearable: item?.clearable ? item.clearable : true,
                style: item.style,
                size: item.size,
                controlsPosition: item.controlsPosition,
            });
        case "select":
            return h(
                ElSelect,
                {
                    modelValue: props.formModel[key],
                    "onUpdate:modelValue": (value: any) => {
                        props.formModel[key] = value;
                    },
                    placeholder: item.placeholder ? item.placeholder : `请选择${item.label}`,
                    size: item.size,
                    style: item.style,
                    clearable: item?.clearable ? item.clearable : true,
                    multiple: item.multiple,
                    filterable: item.filterable,
                },
                () =>
                    item.options?.map((opt: any, ind: number) =>
                        h(ElOption, {
                            key: `${key}-${ind}`,
                            label: opt.label,
                            value: opt.value,
                        })
                    )
            );
        case "tree-select":
            return h(ElTreeSelect, {
                modelValue: props.formModel[key],
                "onUpdate:modelValue": (value: any) => {
                    props.formModel[key] = value;
                },
                data: item?.options,
                renderAfterExpand: item.renderAfterExpand,
                checkStrictly: item.checkStrictly,
                showCheckbox: item.showCheckbox,
                placeholder: item.placeholder || item.readonly ? item.placeholder : `请选择${item.label}`,
                size: item.size,
                style: item.style,
                clearable: item?.clearable ? item.clearable : true,
                multiple: item.multiple,
                filterable: item.filterable,
            });
        case "datetime":
            return h(ElDatePicker, {
                modelValue: props.formModel[key],
                "onUpdate:modelValue": (value: any) => {
                    props.formModel[key] = value;
                },
                type: "datetime",
                placeholder: item.placeholder ? item.placeholder : `请选择${item.label}`,
                format: "YYYY-MM-DD HH:mm:ss",
                valueFormat: "YYYY-MM-DD HH:mm:ss",
                clearable: item?.clearable ? item.clearable : true,
                style: item.style,
                size: item.size,
            });
        case "date":
            return h(ElDatePicker, {
                modelValue: props.formModel[key],
                "onUpdate:modelValue": (value: any) => {
                    props.formModel[key] = value;
                },
                type: "date",
                placeholder: item.placeholder ? item.placeholder : `请选择${item.label}`,
                format: "YYYY-MM-DD",
                valueFormat: "YYYY-MM-DD",
                clearable: item?.clearable ? item.clearable : true,
                style: item.style,
                size: item.size,
            });
        case "time":
            return h(ElTimePicker, {
                modelValue: props.formModel[key],
                "onUpdate:modelValue": (value: any) => {
                    props.formModel[key] = value;
                },
                placeholder: item.placeholder ? item.placeholder : `请选择${item.label}`,
                style: item.style,
                size: item.size,
                clearable: item?.clearable ? item.clearable : true,
                valueFormat: "HH:mm:ss",
                format: "HH:mm:ss",
            });
        default:
            return "";
    }
};

//渲染按钮
const renderButtons = () => {
    const buttons: VNode[] = [];
    if (props.showSearch && hasPermission(props.searchPermission)) {
        buttons.push(
            h(
                ElButton,
                {
                    type: "primary",
                    size: size.value,
                    icon: Search,
                    onClick: onSearch,
                },
                () => "查询"
            )
        );
    }
    if (props.showClear && hasPermission(props.searchPermission)) {
        buttons.push(
            h(
                ElButton,
                {
                    type: "warning",
                    size: size.value,
                    icon: Close,
                    onClick: onClear,
                },
                () => "清空"
            )
        );
    }
    if (props.showAdd && hasPermission(props.addPermission)) {
        buttons.push(
            h(
                ElButton,
                {
                    type: "success",
                    size: size.value,
                    icon: Plus,
                    onClick: onAdd,
                },
                () => "添加"
            )
        );
    }
    return h(Fragment, {}, buttons);
};

//渲染展开折叠按钮
const renderExpandButton = () => {
    if (props.showExpand) {
        return h(ElTooltip, { content: isFullScreen.value ? "退出全屏" : "全屏", placement: "top" }, { default: () => h(ElButton, { onClick: onExpand, circle: true, size: size.value }, { default: () => (isFullScreen.value ? shrink() : extend()) }) });
    }
    return null;
};

//展开收起处理
const onExpand = () => {
    isFullScreen.value = !isFullScreen.value;
};

//使用defineEmits注册一个自定义事件,子传父
const emit = defineEmits(["onSearch", "onAdd"]);

//触发搜索事件
const onSearch = debounce(() => emit("onSearch", props.formModel), 200);

//触发清空事件
const onClear = () => {
    for (const key in props.formModel) {
        props.formModel[key] = null;
    }
};

//触发添加事件
const onAdd = () => emit("onAdd");

const scrollFormRef = ref<HTMLElement | null>(null);
//滚动处理
const doScroll = () => {
    const wrapper = scrollFormRef.value;
    if (wrapper) {
        wrapper.addEventListener("wheel", (e) => {
            if (e.deltaY !== 0) {
                e.preventDefault();
                wrapper.scrollLeft += e.deltaY;
            }
        });
        //判断是否有水平滚动条，如果没有就设置布局 靠右
        if (wrapper.scrollWidth <= wrapper.clientWidth) {
            wrapper.style.display = "flex";
            wrapper.style.justifyContent = "flex-end";
        }
    }
};

//表单按钮的key
const formBtnKey = ref<string>(`form-btn-${new Date().getTime()}`);

const handleClick = (_event: MouseEvent) => {
    formBtnKey.value = `form-btn-${new Date().getTime()}`;
};

// 鼠标滚轮滚动处理
onMounted(() => {
    doScroll();
    document.addEventListener("click", handleClick);
});

//组件销毁时取消防抖
onUnmounted(() => {
    onSearch.cancel();
    document.removeEventListener("click", handleClick);
});
</script>

<style scoped lang="less">
@import "@/assets/less/common.less";
// .form {
//     float: right;
//     width: 100%; /* 或者你希望的宽度 */
//     overflow-x: auto; /* 启用水平滚动 */
//     white-space: nowrap; /* 保持子元素在一行内 */
// }
.container {
    position: relative;
    width: 100%;
    .form {
        display: flex;
        width: 100%;
        position: relative;
        justify-content: end;
        .form-item {
            flex: 1;
            overflow-x: auto;
            overflow-y: hidden;
            white-space: nowrap;
            //padding-bottom: 8px; /* 为滚动条留出空间 */
            scrollbar-width: none; /* 不显示滚动条 */

            /* 确保所有表单项在一行 */
            // .el-form-item {
            //     display: inline-block;
            //     margin-right: 16px;
            //     vertical-align: top;
            // }
            :deep(.el-form-item .el-select) {
                width: 180px;
            }
            :deep(.el-form-item .el-input) {
                width: 180px;
            }
            :deep(.el-form-item .el-input-number) {
                width: 180px;
            }
        }
        .form-btn {
            position: sticky;
            right: 0;
            //background: white;
            padding-left: 16px;
            z-index: 1;
            //box-shadow: -5px 0 10px -5px rgba(0, 0, 0, 0.1);
            .form-btn-item {
                margin-right: 0;
            }
        }
    }
    .form-dialog {
        :deep(.el-form-item .el-select) {
            width: 180px;
        }
        :deep(.el-form-item .el-input) {
            width: 180px;
        }
        :deep(.el-form-item .el-input-number) {
            width: 180px;
        }
    }
}
</style>
